
#include "poller.h"
#include <iostream>

using namespace as::snet;


Poller::Poller(PollerInstance &poll_inc)
    :m_pollInc(poll_inc)
{
#ifdef _WIN32
    m_ioPort = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0);
#else
    m_ioPort = ::epoll_create1(EPOLL_CLOEXEC);
#endif
}

bool Poller::add(socket_fd fd, void *key)
{
#ifdef _WIN32
    return ::CreateIoCompletionPort((HANDLE)fd, m_ioPort, (ULONG_PTR)key, 0);
#else
    epoll_event ev = {};
    memset(ev, 0, sizeof(ev));
    ev.event = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLERR | EPOLLET;
    ev.data.ptr = key;
    return ::epoll_ctl(m_ioPort, EPOLL_CTL_ADD, fd, &ev);
#endif
}

void Poller::poll()
{
    auto events = m_events.data();
#ifdef _WIN32
    ULONG num;
    if(GetQueuedCompletionStatusEx(m_ioPort, events, (ULONG)m_events.size(), &num, 0, false) == false)
    {
        auto err = BaseSocket::get_last_err();
        if(WAIT_TIMEOUT == err)
        {
            //todo log
        }
        else
        {
            std::cout << "error:" << err <<std::endl;
        }
        return;
    }

    for(int i = 0; i < (int)num; ++i)
    {
        auto &ev = m_events[i];
        auto key = reinterpret_cast<void*>(ev.lpCompletionKey);
        m_pollInc.on_poll(key, &ev);
    }
#else
    num = epoll_wait(m_ioPort, m_events, m_events.size(), 0);
    if(num <= 0)
    {
        //todo log
        return;
    } 

    for(int i = 0; i < num; ++i)
    {
        auto &ev = m_events[i];
        auto key = ev.data.ptr;
        m_pollInc.on_poll(key, &ev);
    }
#endif
}